#include "PrecompiledHeaders.h"
#include "MenuState.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////// EVENT HANDLER FUNCTIONS ////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool MenuState::frameEnded(const Ogre::FrameEvent &evt)
{
	if (resources->joystick != NULL)
	{
		if (resources->joystick->next()) nextButton();
		else if (resources->joystick->previous()) prevButton();
		else if (resources->joystick->triggerPressed()) clickButton();
		else if (resources->joystick->quit()) MenuState::popGameState();
	}
	return true;
}

// Unsubscribes a button from it's MouseLeaves events
void MenuState::unsubscribeButton(Ogre::String buttonName)
{
    CEGUI::Window *button = (CEGUI::Window*)CEGUI::WindowManager::getSingleton().getWindow(buttonName);
    button->removeEvent(CEGUI::PushButton::EventMouseLeaves);
	button->removeEvent(CEGUI::PushButton::EventMouseEnters);
}

void MenuState::setWindowText(Ogre::String windowName, Ogre::String newText)
{
    CEGUI::Window *win = (CEGUI::Window*)CEGUI::WindowManager::getSingleton().getWindow(windowName);
    win->setText(newText);
}

void MenuState::setWindowColour(Ogre::String windowName, Ogre::String newColour)
{
	CEGUI::Window *win = (CEGUI::Window*)CEGUI::WindowManager::getSingleton().getWindow(windowName);
    win->setProperty("NormalTextColour", newColour);
	win->setProperty("HoverTextColour", newColour);
}

void MenuState::setWindowImage(Ogre::String windowName, Ogre::String imageName)
{
    CEGUI::Window *win = (CEGUI::Window*)CEGUI::WindowManager::getSingleton().getWindow(windowName);
    win->setProperty("Image", imageName);
}

// Adds an embedded window to the sheet
void MenuState::addEmbeddedWindow(Ogre::String layout)
{
    CEGUI::Window* element = CEGUI::WindowManager::getSingletonPtr()->loadWindowLayout(layout);
    resources->GUISystem->getGUISheet()->addChildWindow(element);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////// MOUSE INPUT FUNCTIONS //////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*
 * Function that converts OIS input from mouse buttons to CEGUI-compliant input
 */
CEGUI::MouseButton MenuState::convertButton(OIS::MouseButtonID buttonID)
{
    switch (buttonID) {
        case OIS::MB_Left:   return CEGUI::LeftButton;
        case OIS::MB_Right:  return CEGUI::RightButton;
        case OIS::MB_Middle: return CEGUI::MiddleButton;
        default:             return CEGUI::LeftButton;
    }
}

/*
 * MouseListener functions - Inject OIS mouse events in to CEGUI
 */
bool MenuState::mouseMoved(const OIS::MouseEvent & e)
{
    CEGUI::System::getSingleton().injectMouseMove(e.state.X.rel, e.state.Y.rel);
    return true;
}

bool MenuState::mousePressed(const OIS::MouseEvent & e, OIS::MouseButtonID ID)
{
    CEGUI::System::getSingleton().injectMouseButtonDown(convertButton(ID));
    return true;
}

bool MenuState::mouseReleased(const OIS::MouseEvent & e, OIS::MouseButtonID ID)
{
    CEGUI::System::getSingleton().injectMouseButtonUp(convertButton(ID));
    return true;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////// KEYBOARD INPUT FUNCTIONS ///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool MenuState::keyPressed(const OIS::KeyEvent & e)
{
    CEGUI::System *sys = CEGUI::System::getSingletonPtr();
    sys->injectKeyDown(e.key);
    sys->injectChar(e.text);
    
	switch (e.key)
    {
        case OIS::KC_ESCAPE:
            MenuState::popGameState();
            break;
		case OIS::KC_LEFT:
			prevButton();
			break;
		case OIS::KC_UP:
			prevButton();
			break;
		case OIS::KC_RIGHT:
			nextButton();
			break;
		case OIS::KC_DOWN:
			nextButton();
			break;
		case OIS::KC_RETURN:
			clickButton();
			break;
        default:
            break;
    }
    
    return true;
}

bool MenuState::keyReleased(const OIS::KeyEvent & e)
{
    // Simulates the left mouse button being released when the key is released
    CEGUI::System::getSingleton().injectMouseButtonUp(convertButton(OIS::MB_Left));
    return true;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////// JOYSTICK INPUT FUNCTIONS ///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Increases the iterator so that the next button is selected
void MenuState::nextButton()
{
	winIterator++;
	if (winIterator == activeWindows.end())
	{
		winIterator = activeWindows.begin();
	}
	moveMouse();
}

// Decreases the iterator so that the previous window is selected
void MenuState::prevButton()
{
	if (winIterator == activeWindows.begin())
	{
		winIterator = activeWindows.end();
	}
	winIterator--;
	moveMouse();
}

// Simulates a mouse click
void MenuState::clickButton()
{
	CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::LeftButton);
	CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::LeftButton);
}

// Moves the mouse cursor to the position of the current window
void MenuState::moveMouse()
{
	CEGUI::System::getSingleton().injectMousePosition(winIterator->x, winIterator->y);
}

// Adds a window position to the activeWindows vector
void MenuState::addWinPos(CEGUI::Window *button, bool offsetX)
{
	WinPos newWinPos;
	newWinPos.x = CEGUI::CoordConverter::windowToScreenX(*button->getParent(), button->getPosition().d_x);
	newWinPos.y = CEGUI::CoordConverter::windowToScreenY(*button->getParent(), button->getPosition().d_y);
	if (offsetX) newWinPos.x = newWinPos.x + button->getSize().d_x.asAbsolute(resources->config->getResolutionWidth()) - 5;
	else newWinPos.x = newWinPos.x + 10;
	newWinPos.y = newWinPos.y + button->getSize().d_y.asAbsolute(resources->config->getResolutionHeight()) - 5;
	activeWindows.push_back(newWinPos);
}
